// @HEADER
//*********************************************************************//
//  SiYuan: A numerical PDE solver                                     //
//  Copyright (2022) YUAN Xi                                           //
//  This Software is released under the BSD 2-Clause license detailed  //
//  in the file "LICENSE" in the top-level SiYuan directory            //
//*********************************************************************//
// @HEADER

#include "PhysicsBlock.hpp"
#include "EquationSet_Impl.hpp"

namespace SiYuan {

PhysicsBlock::
PhysicsBlock(const Teuchos::RCP<Teuchos::ParameterList>& physics_block_plist,
            const std::string & element_block_id,
             const std::string & material_id,
            const int default_integration_order,
            const panzer::CellData & cell_data,
            const Teuchos::RCP<const panzer::EquationSetFactory>& factory,
            const Teuchos::RCP<panzer::GlobalData>& global_data,
            const bool build_transient_support,
            const std::vector<std::string>& tangent_param_names)
: panzer::PhysicsBlock(physics_block_plist,element_block_id,default_integration_order,
    cell_data,factory,global_data,build_transient_support,tangent_param_names)
{ _material_name=material_id; };


// *******************************************************************
void PhysicsBlock::
buildAndRegisterClosureModelEvaluators(PHX::FieldManager<panzer::Traits>& fm,
                                   const panzer::ClosureModelFactory_TemplateManager<panzer::Traits>& factory,
                                   const Teuchos::ParameterList& models,
                                   const Teuchos::ParameterList& user_data) const
{
  using namespace panzer;

  // Loop over equation set template managers
  for ( const auto& eq_set : m_equation_sets ) {

    // Loop over evaluation types
    EquationSet_TemplateManager<panzer::Traits> eqstm = *eq_set;
    EquationSet_TemplateManager<panzer::Traits>::iterator eval_type =
      eqstm.begin();
    int idx = 0;
    for (; eval_type != eqstm.end(); ++eval_type,++idx) {
      if (m_active_evaluation_types[idx]) {

        // Loop over integration rules
        for (std::map<int,Teuchos::RCP<panzer::IntegrationRule> >::const_iterator ir_iter = m_integration_rules.begin();
             ir_iter != m_integration_rules.end(); ++ ir_iter) {

          Teuchos::RCP<panzer::IntegrationRule> ir = ir_iter->second;

          const int di = eval_type->setDetailsIndex(this->getDetailsIndex());
          eval_type->buildAndRegisterClosureModelEvaluators(fm, *m_field_lib->buildFieldLayoutLibrary(*ir), ir, factory, models, user_data);
          eval_type->setDetailsIndex(di);
        }
      }
    }
  }
}


void PhysicsBlock::
buildAndRegisterClosureModelEvaluators(PHX::FieldManager<panzer::Traits>& fm,
                               const panzer::ClosureModelFactory_TemplateManager<panzer::Traits>& factory,
                               const std::string& model_name,
                               const Teuchos::ParameterList& models,
                               const Teuchos::ParameterList& user_data) const
{
  using namespace panzer;

  // Loop over equation set template managers
  for ( const auto& eq_set : m_equation_sets) {

    // Loop over evaluation types
    EquationSet_TemplateManager<panzer::Traits> eqstm = *eq_set;
    EquationSet_TemplateManager<panzer::Traits>::iterator eval_type =
      eqstm.begin();
    int idx = 0;
    for (; eval_type != eqstm.end(); ++eval_type,++idx) {
      if (m_active_evaluation_types[idx]) {

        // Loop over integration rules
        for (std::map<int,Teuchos::RCP<panzer::IntegrationRule> >::const_iterator ir_iter = m_integration_rules.begin();
             ir_iter != m_integration_rules.end(); ++ ir_iter) {

          Teuchos::RCP<panzer::IntegrationRule> ir = ir_iter->second;
          const int di = eval_type->setDetailsIndex(this->getDetailsIndex());
          eval_type->buildAndRegisterClosureModelEvaluators(fm, *m_field_lib->buildFieldLayoutLibrary(*ir), ir, factory, model_name, models, user_data);
          eval_type->setDetailsIndex(di);
        }
      }
    }
  }
}

// *******************************************************************
void PhysicsBlock::
setMaterial(PHX::FieldManager<panzer::Traits>& fm, CMaterials& matls )
{
  if( matls.empty() ) return;

  for ( const auto& eq_set : m_equation_sets ) {

    // Loop over evaluation types
    panzer::EquationSet_TemplateManager<panzer::Traits> eqstm = *eq_set;
    panzer::EquationSet_TemplateManager<panzer::Traits>::iterator eval_type =
      eqstm.begin();
    int idx = 0;
    for (; eval_type != eqstm.end(); ++eval_type,++idx) {
      if (m_active_evaluation_types[idx]) {
        // Do not loop over integration rules.  Only call this for the
        // ir that the residual is integrated over.  Otherwise the
        // residual gets contributions from multiple integrations of the
        // same cell!  This ir is only known by equaiton set.
      //  const int di = eval_type->setDetailsIndex(this->getDetailsIndex());
        std::shared_ptr<Material> cmatl = matls.at(_material_name);
        eval_type->setMaterial(fm,cmatl);
      //  eval_type->setDetailsIndex(di);
      }
    }
  }

}


}
